#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 510, M = 100010;

int n1, n2, m; // 左半部的点数 n1, 右半部的点数 n2, m为总边数 
int h[N], e[M], ne[M], idx; // 稀疏图， 用邻接表存储 
int match[N]; //存放该点匹配成功的点 
bool st[N]; //标记是否被进行匹配过，（即 判重） 

void add(int a, int b) { //存储从a点指向b点的边 
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

bool find(int x) { //用来查找x点是否能匹配成功 
	for (int i = h[x]; i != -1; i = ne[i]) { //遍历与该点有联通的点 
		int j = e[i]; // 取该结点 
		if (!st[j]) { // 如果该点还未被查找过 
			st[j] = true; //将该点标记已被查找过 
			if (match[j] == 0 || find(match[j])) { //如果该点还未匹配 或者 该点匹配的点还能成功匹配其他点 
				match[j] = x; // 则将该点与x点成功匹配 
				return true; // 说明x点能匹配成功，则返回 true 
			}
		}
	}
	
	return false; // 否则说明x点无法匹配成功，则返回 false
}

int main() {
	scanf("%d%d%d", &n1, &n2, &m); // 输入左半部的点数 n1, 右半部的点数 n2, 总边数 m
	
	memset(h, -1, sizeof h); // 初始化邻接表的所有表头为 -1 
	
	while (m -- ) {
		int a, b;
		scanf("%d%d", &a, &b); // 输入a,b两点 
		add(a, b); /* 存储由a指向b的边
	（虽然此处为无向图，但是只需要将左半部的点一一进行查找匹配，所以只需要存储由左半部指向右半部的有向边即可）*/		 
	}
	
	int res = 0; // 存储成功匹配的个数 
	for (int i = 1; i <= n1; i ++ ) { //遍历左半部的点 
		memset(st, false, sizeof st); //遍历每个点都将st[]数组给全部初始化为 false 来进行匹配查找 
		if (find(i)) res ++ ; // 如果该点成功匹配， res ++ （即匹配成功个数 +1） 
	}
	
	printf("%d\n", res); // 输出最大匹配个数 
	
	return 0; // 结束 
}